package com.yourbatis.syntax;

import com.yourbatis.lexical.Token;
import com.yourbatis.lexical.TokenType;

import java.util.ArrayList;
import java.util.List;

import static com.yourbatis.syntax.Keywords.*;

public class Syntax {


    List<ASTNode> nodeList = new ArrayList<>();
    List<Token> tokenize = new ArrayList<>();
    int pos = 0;


    public Syntax(List<Token> tokenize){
        if (tokenize.size() == 0){
            throw new RuntimeException("ASTNode is null");
        }
        this.tokenize = tokenize;
        parser();
    }


    public void parser(){
        while (!match(TokenType.EOF)){
            nodeList.add(parseStatement());
        }
    }

    private Statement  parseStatement() {
        // 变量赋值语句 (如 x = 10)
        if (lookaheadIsAssignment()) {
            return parseAssignment();
        }
        // if语句
        if (match(TokenType.KEYWORD, IF)) {
            return parseIfStatement();
        }
        if (match(TokenType.KEYWORD, FOR)) {
            return parseForStatement();
        }
        if (match(TokenType.KEYWORD, FUN)) {
            return parseFunStatement();
        }
        // return语句
        if (match(TokenType.KEYWORD, RETURN)) {
            return parseReturnStatement();
        }
        // 如果是 print 语句
        if (match(TokenType.KEYWORD, PRINT)) {
            return parsePrintStatement();
        }
        // 否则解析为表达式语句
        Expression expr = parseExpression();
        if (match(TokenType.DELIMITER, ";")) {
            consume(TokenType.DELIMITER, ";");
        }
        return new ExpressionStatement(expr);
//        throw new RuntimeException("error");
    }

    private FunctionCall parseFunctionCall() {
        String name = currentToken().getValue();
        consume(TokenType.IDENTIFIER);
        consume(TokenType.DELIMITER, "(");

        List<Expression> arguments = new ArrayList<>();
        if (!match(TokenType.DELIMITER, ")")) {
            do {
                consume(TokenType.DELIMITER, ",");
                arguments.add(parseExpression());
            } while (match(TokenType.DELIMITER, ","));
        }
        consume(TokenType.DELIMITER, ")");

        return new FunctionCall(name, arguments);
    }

    private Statement parseReturnStatement() {
        consume(TokenType.KEYWORD, "return");
        Expression expr = null;
        if (!match(TokenType.DELIMITER, ";")) {
            expr = parseExpression();
        }
        if (match(TokenType.DELIMITER, ";")) {
            consume(TokenType.DELIMITER, ";");
        }
        return new ReturnStatement(expr);
    }

    private Statement parseFunStatement() {
        consume(TokenType.KEYWORD, FUN);
        String name = currentToken().getValue();
        consume(TokenType.IDENTIFIER);
        consume(TokenType.DELIMITER, "(");

        // 解析参数列表
        List<String> parameters = new ArrayList<>();
        if (!match(TokenType.DELIMITER, ")")) {
            do {
                consume(TokenType.DELIMITER, ",");
                parameters.add(currentToken().getValue());
                consume(TokenType.IDENTIFIER);
            } while (match(TokenType.DELIMITER, ","));
        }
        consume(TokenType.DELIMITER, ")");

        // 解析函数体
        BlockStatement body = (BlockStatement)parseBlockOrSingleStatement();
        return new FunStatement(name, parameters, body);
    }

    private Statement parseForStatement() {
        consume(TokenType.KEYWORD, FOR);
        if (match(TokenType.DELIMITER, "(")) {
            consume(TokenType.DELIMITER, "(");
        }
        // 解析变量
        Statement variable = parseAssignment();
        // 解析条件
        Expression expression = parseExpression();
        if (match(TokenType.DELIMITER, ";")) {
            consume(TokenType.DELIMITER, ";");
        }
        // 解析自增
        Expression update = parsePrimary();

        Statement block = parseBlockOrSingleStatement();

        return new ForStatement(variable, expression, update, block);
    }

    /**
     * 处理if
     * @return
     */
    private Statement parseIfStatement() {
        consume(TokenType.KEYWORD, IF);
        boolean leftDelimiter = false;
        if (match(TokenType.DELIMITER, "(")) {
            consume(TokenType.DELIMITER, "(");
            leftDelimiter = !leftDelimiter;
        }
//        consume(TokenType.DELIMITER, "(");
//        Expression condition = parseExpression();
        Expression condition = parseLogicalExpression();
        if(leftDelimiter){
            consume(TokenType.DELIMITER, ")");
        }

        Statement thenBranch = parseBlockOrSingleStatement();
        Statement elseBranch = null;

        // 解析else分支(可选)
        if (match(TokenType.KEYWORD, "else")) {
            consume(TokenType.KEYWORD, "else");
            elseBranch = parseBlockOrSingleStatement();
        }

        return new IfStatement(condition, thenBranch, elseBranch);
    }



    /**
     * 方法体
     * @return
     */
    private Statement parseBlockOrSingleStatement() {
        // 检查是否是大括号代码块
        if (match(TokenType.DELIMITER, "{")) {
            consume(TokenType.DELIMITER, "{");
            List<Statement> statements = new ArrayList<>();

            while (!match(TokenType.DELIMITER, "}") && !match(TokenType.EOF)) {
                statements.add(parseStatement());
            }

            consume(TokenType.DELIMITER, "}");
            return new BlockStatement(statements);
        }
        // 单条语句
        return parseStatement();
    }

    private boolean lookaheadIsAssignment() {
        // 检查是否是赋值模式: IDENTIFIER = ...
        return match(TokenType.IDENTIFIER) &&
                tokenize.size() > pos + 1 &&
                tokenize.get(pos + 1).getType() == TokenType.OPERATOR &&
                tokenize.get(pos + 1).getValue().equals("=");
    }

    /**
     * 变量
     * @return
     */
    private Statement parseAssignment() {
        String varName = currentToken().getValue();
        consume(TokenType.IDENTIFIER);
        consume(TokenType.OPERATOR, "=");
        Expression expr = parseExpression();
        if (match(TokenType.DELIMITER, ";")) {
            consume(TokenType.DELIMITER, ";");
        }
        return new AssignmentStatement(varName, expr);
    }

    /**
     * 处理形参
     * @return
     */
    private Statement parseParameter() {
        String varName = currentToken().getValue();
        consume(TokenType.IDENTIFIER);
        if (match(TokenType.OPERATOR, "=")) {
            consume(TokenType.OPERATOR, "=");
            Expression expr = parseExpression();

        }
        return new ParameterStatement(varName);
    }

    /**
     * print
     * @return
     */
    private Statement  parsePrintStatement() {
        consume(TokenType.KEYWORD, PRINT);
        if (match(TokenType.DELIMITER, "(")) {
            consume(TokenType.DELIMITER, "(");
        }
        Expression expr = parseExpression();
        if (match(TokenType.DELIMITER, ")")) {
            consume(TokenType.DELIMITER, ")");
        }
        if (match(TokenType.DELIMITER, ";")) {
            consume(TokenType.DELIMITER, ";");
        }
        return new PrintStatement(expr);
    }

    /**
     * 表达式
     * @return
     */
    private Expression parseExpression() {
        Expression left = parseTerm(); // 解析高优先级项（* /）
        while (
                match(TokenType.OPERATOR, "+") ||
                match(TokenType.OPERATOR, "-") ||
                match(TokenType.COMPARISON, "==") ||
                match(TokenType.COMPARISON, ">") ||
                match(TokenType.COMPARISON, "<") ||
                match(TokenType.COMPARISON, ">=") ||
                match(TokenType.COMPARISON, "<=") ||
                match(TokenType.COMPARISON, "!=")
        ) {
            String op = currentToken().getValue();
            advance();
            left = new BinaryExpression(left, op, parseTerm());
        }
        return left;
    }

    private Expression parseLogicalExpression() {
        Expression left = parseExpression();
        while (match(TokenType.LOGICAL, "&&") || match(TokenType.LOGICAL, "||")) {
            String op = currentToken().getValue();
            advance();
            left = new LogicalExpression(left, op, parseExpression());
        }
        return left;
    }

    private Expression parseTerm() {
        Expression left = parsePrimary(); // 解析基本表达式（数字、括号等）
        while (match(TokenType.OPERATOR, "*") || match(TokenType.OPERATOR, "/")) {
            String op = currentToken().getValue();
            advance();
            left = new BinaryExpression(left, op, parsePrimary());
        }
        return left;
    }

    private Expression parsePrimary() {
        if (match(TokenType.NUMBER)) {
            int value = Integer.parseInt(currentToken().getValue());
            advance();
            return new NumberLiteral(value);
        }
        if (match(TokenType.DELIMITER, "(")) {
            consume(TokenType.DELIMITER, "(");
            Expression expr = parseExpression();
            consume(TokenType.DELIMITER, ")");
            return expr;
        }

        if (match(TokenType.KEYWORD)) {
            String name = currentToken().getValue();
            advance();

            // 检查是否是自增运算
            if (match(TokenType.OPERATOR, "++")) {
                consume(TokenType.OPERATOR, "++");
                return new PostfixIncrement(name);
            }
            // 检查是否是前缀自增（可选）
            if (lookaheadIsPrefixIncrement(name)) {
                return parsePrefixIncrement(name);
            }
            if(name.equals(NULL) || name.equals(TRUE) || name.equals(FALSE)){
                return new KeywordExpression(name);
            }

            // 普通变量引用
            return new VariableReference(name);
        }

        // 变量引用
        if (match(TokenType.IDENTIFIER)) {
            if(tokenize.size() > pos + 1 &&
                    tokenize.get(pos + 1).getType() == TokenType.DELIMITER &&
                    tokenize.get(pos + 1).getValue().equals("(")){
                return parseFunctionCall();
            }
            String name = currentToken().getValue();
            advance();
            return new VariableReference(name);
        }

        // 字符串
        if (match(TokenType.STRING)) {
            String value = currentToken().getValue();
            advance();
            return new StringLiteral(value);
        }


        throw new RuntimeException("Expected statement, got " + currentToken().getValue());
    }

    private boolean lookaheadIsPrefixIncrement(String name) {
        return false;
    }

    private Expression parsePrefixIncrement(String name) {
        return null;
    }

    private Token currentToken() {
        return tokenize.get(pos);
    }

    private void advance() {
        pos++;
    }

    private void consume(TokenType type, String value) {
        if (!match(type, value)) {
            throw new RuntimeException("Expected " + value + ", got " + currentToken().getValue());
        }
        advance();
    }

    private void consume(TokenType type) {
        if (!match(type)) {
            throw new RuntimeException("Expected " + type  + ", got " + currentToken().getValue());
        }
        advance();
    }

    private boolean match(TokenType type) {
        return pos < tokenize.size() && tokenize.get(pos).getType() == type;
    }

    private boolean match(TokenType type, String value) {
        return pos < tokenize.size() &&
                tokenize.get(pos).getType() == type &&
                tokenize.get(pos).getValue().equals(value);
    }

    public List<ASTNode> getNodeList() {



        return nodeList;
    }




}
